package com.polaris.live.im.sfs.core.bean

import com.polaris.live.im.sfs.ARGUMENTS_DATA
import com.polaris.live.im.sfs.ARGUMENTS_ROOM
import com.polaris.live.im.sfs.ARGUMENTS_USER
import com.polaris.live.im.utils.SmartFoxUtils
import com.polaris.live.common.util.computeIfAbsentBy21
import com.smartfoxserver.v2.entities.data.SFSObject
import sfs2x.client.entities.SFSRoom
import sfs2x.client.entities.SFSUser
import kotlin.reflect.KClass

/**
 * DataArgument
 *
 * @author Created by lucas on 2023/10/19 15:58
 */
class DataArgument(
    val command: String,
    val arguments: Map<String, Any>,
) {

    val timestamp = System.currentTimeMillis()

    private val cache = HashMap<String, AbstractMessage?>()

    /**
     * 从 Map 中获取数据
     */
    inline fun <reified T : AbstractMessage> getData(): T? {
        return getData(T::class)
    }

    /**
     * 从 Map 中获取数据
     */
    fun <T : AbstractMessage> getData(kClazz: KClass<T>): T? {
        return getData(kClazz) {
            SmartFoxUtils.fromSFSObject(it, kClazz)
        }
    }

    inline fun <reified T : AbstractMessage> getData(noinline block: (SFSObject) -> T?): T? {
        return getData(T::class, block)
    }

    fun <T : AbstractMessage> getData(kClazz: KClass<T>, block: (SFSObject) -> T?): T? {
        val sfsObject = getSfsData() ?: return null

        val msgId = sfsObject.get("msgId")?.`object` as? String
            ?: return null
        val key = msgId + kClazz.qualifiedName

        val res = cache.computeIfAbsentBy21(key) { block(sfsObject) }

        return res as? T
    }

    fun getSfsData(): SFSObject? {
        val obj = arguments[ARGUMENTS_DATA]
        return if (obj is SFSObject) {
            obj
        } else {
            null
        }
    }

    fun getUser(): SFSUser? {
        return arguments[ARGUMENTS_USER] as? SFSUser
    }

    fun getRoom(): SFSRoom? {
        return arguments[ARGUMENTS_ROOM] as? SFSRoom
    }

    fun getMsgId(): String? {
        return getSfsData()?.getText("msgId")
    }

    fun getSeqId(): Long? {
        return getSfsData()?.getLong("seqId")
    }
}

/**
 * 获取roomId
 */
fun SFSRoom?.getRoomId() = (this?.getVariable("userId")?.value as? Number)?.toLong()

/**
 * 获取roomId
 */
fun DataArgument.getRoomId() = (this.getRoom()?.getVariable("userId")?.value as? Number)?.toLong()